﻿using KinonekoSoftware.Foundation.Languages;
using KinonekoSoftware.Foundation.UI.Commands;
using KinonekoSoftware.Foundation;

namespace KinonekoSoftware.Foundation.UI.ViewModels
{
    public abstract class NotifyDialog : DialogCountable, INotifyDialog
    {
        internal readonly TaskCompletionSource TaskCompletionSource;
        private readonly  List<DialogRule> Rules;

        private DialogCloseHandler     _handler;
        private DialogExceptionHandler _exHandler;
        private string                 _completionButtonText;
        private string                 _tempCompletionButtonText;

        protected NotifyDialog()
        {
            TaskCompletionSource = new TaskCompletionSource();
            Rules                = new List<DialogRule>(8);
            CompletionCommand    = new ActionCommand(Finish, CanFinish);
            CancelCommand        = new ActionCommand(Cancel);
            Initialized();
        }

        private void Initialized()
        {
            CreateValidationRules(Rules);
        }
        
        
        protected sealed override void TryFinish()
        {
            CompletionCommand.RaiseUpdate();
        }

        
        internal override void OnSetCountDownText(bool isFinish)
        {
            if (string.IsNullOrEmpty(_tempCompletionButtonText))
                _tempCompletionButtonText = CompletionButtonText;

            if (isFinish)
            {
                CompletionButtonText = _tempCompletionButtonText;
            }
            else
            {
                Remain               = Remain == 0 ? CountDown : Remain;
                CompletionButtonText = $"{_tempCompletionButtonText}（{Remain}）";
            }
        }

        internal sealed override void OnReceiveInternal(DialogContext dc)
        {
            _handler             = dc.CloseHandler;
            _exHandler           = dc.ExceptionHandler;
            CompletionButtonText = string.IsNullOrEmpty(CompletionButtonText) ? LanguageManager.CompletionButtonText : CompletionButtonText;
            CancelButtonText     = string.IsNullOrEmpty(CancelButtonText) ? LanguageManager.CancelButtonText : CancelButtonText;
            OnReceive(dc);
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="context"></param>
        /// <returns>返回一个参数，该参数表示当前对话框是编辑模式还是新建模式？</returns>
        protected virtual void OnReceive(DialogContext context) {}

        /// <summary>
        /// 创建验证规则。
        /// </summary>
        protected virtual void CreateValidationRules(ICollection<DialogRule> rules)
        {
            
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        protected override bool CanFinish()
        {
            if (EnableCountDown)
            {
                return Remain <= CountDown;
            }

            return true;
        }

        /// <summary>
        /// 
        /// </summary>
        public void Cancel()
        {
            //
            //
            TaskCompletionSource.SetResult();

            //
            // 关闭对话框
            _handler(this);
        }

        /// <summary>
        /// 尝试完成对话框，并关闭对话框
        /// </summary>
        public void Finish()
        {
            try
            {
                if (!CanFinish())
                {
                    return;
                }

                //
                //
                TaskCompletionSource.SetResult();

                //
                // 关闭对话框
                _handler(this);
            }
            catch(Exception ex)
            {
                _exHandler(this, ex);
                TaskCompletionSource.SetException(ex);
            }
        }
        
        /// <summary>
        /// 获取或设置 <see cref="CompletionButtonText"/> 属性。
        /// </summary>
        public string CompletionButtonText
        {
            get => _completionButtonText;
            set => SetValue(ref _completionButtonText, value);
        }
        
        public ActionCommand CompletionCommand { get; }
    }
}